package cn.ric.mycurd.beanconfigs;

import java.util.Objects;

import javax.sql.DataSource;

import cn.ric.mycurd.plugin.DynamicSqlInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.StringUtils;

/**
 * @author ric.zhang
 */
public class MycurdDataSourceFactory extends DataSourceProperties {
    private boolean enableDynamicSqlInterceptor;
    private String mybatisConfigLocation;
    private String mapperLocations;
    private String typeAliasesPackage;
    private DataSource build;

    public void setEnableDynamicSqlInterceptor(boolean enableDynamicSqlInterceptor) {
        this.enableDynamicSqlInterceptor = enableDynamicSqlInterceptor;
    }

    public void setMybatisConfigLocation(String mybatisConfigLocation) {
        this.mybatisConfigLocation = mybatisConfigLocation;
    }

    public void setMapperLocations(String mapperLocations) {
        this.mapperLocations = mapperLocations;
    }

    public void setTypeAliasesPackage(String typeAliasesPackage) {
        this.typeAliasesPackage = typeAliasesPackage;
    }

    public DataSource createDataSource() {
        if (build == null) {
            build = this.initializeDataSourceBuilder().build();
        }
        return build;
    }

    public SqlSessionTemplate createSqlSessionTemplate() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(createDataSource());
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        if (StringUtils.hasText(mapperLocations)) {
            factoryBean.setMapperLocations(resolver.getResources(mapperLocations));
        }
        if (StringUtils.hasText(mybatisConfigLocation)) {
            factoryBean.setConfigLocation(resolver.getResource(mybatisConfigLocation));
        } else {
            factoryBean.setConfigLocation(resolver.getResource("classpath:/mybatis-config-default.xml"));
        }
        if (StringUtils.hasText(typeAliasesPackage)) {
            factoryBean.setTypeAliasesPackage(typeAliasesPackage);
        }
        final SqlSessionFactory sqlSessionFactory = Objects.requireNonNull(factoryBean.getObject());
        if (enableDynamicSqlInterceptor) {
            DynamicSqlInterceptor dynamicSqlInterceptor = null;
            for (Interceptor interceptor : sqlSessionFactory.getConfiguration().getInterceptors()) {
                if (interceptor instanceof DynamicSqlInterceptor) {
                    dynamicSqlInterceptor = (DynamicSqlInterceptor) interceptor;
                }
            }
            if (dynamicSqlInterceptor == null) {
                dynamicSqlInterceptor = new DynamicSqlInterceptor();
                sqlSessionFactory.getConfiguration().addInterceptor(dynamicSqlInterceptor);
            }
        }
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    public DataSourceTransactionManager createTransactionManager() {
        return new DataSourceTransactionManager(createDataSource());
    }
}
